// 1.socket通信：收发功能   2.调用api识别人脸
#include<iostream>
#include<opencv2/opencv.hpp>
#include"aip-cpp-sdk-0.8.1/face.h"
#include<jsoncpp/json/json.h>
#include<unistd.h>
#include<ctime>
#include<string.h>
#include<pthread.h>
#include<stdio.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include<cstring>

using namespace Json;
using namespace cv;
using namespace std;
using namespace aip;

string app_id="26598357";
string api_key="2Tqh9u1mykfhucFd2f2893bG";
string secret_key="1RTVmmMegqtkbWODSL3KTgaS99aYv1YP";

Face client(app_id, api_key, secret_key);
pthread_mutex_t g_lock;
string image = "";
char res[1024] ;
Mat frame;
int flag = 0;


void *search_face(void *arg) {

    Value result;
    Value result2;
    while (1) {
//        namedWindow("detect");
        if (image.size()) {


            result = client.detect(image, "BASE64", aip::null);

            //cout << result["result"]["face_num"] << endl;
            int face_num = result["result"]["face_num"].asInt();
            int left = result["result"]["face_list"][0]["location"]["left"].asInt();
            int top = result["result"]["face_list"][0]["location"]["top"].asInt();
            int width = result["result"]["face_list"][0]["location"]["width"].asInt();
            int height = result["result"]["face_list"][0]["location"]["height"].asInt();
            if (face_num == 1) {

                result2 = client.search(image, "BASE64", "dlq", aip::null);

                string user_id = result2["result"]["user_list"][0]["user_id"].toStyledString();
                int score = result2["result"]["user_list"][0]["score"].asInt();
               // cout << user_id << endl;
                putText(frame,user_id,Point(100,100),FONT_HERSHEY_DUPLEX,1,Scalar(0,0,255),4,8);
                 pthread_mutex_lock(&g_lock);
		if(score >= 70){
			sprintf(res , "%s score:%d  judge: true", user_id.c_str(), score);
		}else{
			sprintf(res, "%s score:%d   judge:false", user_id.c_str(), score);
		}
                pthread_mutex_unlock(&g_lock);

            }
            // cout<<"left="<<left<<endl;
            // cout<<"top="<<top<<endl;
            // cout<<"width="<<width<<endl;
            // cout<<"height="<<height<<endl;

            rectangle(frame, Point(left, top), Point(left + width, top + height), CV_RGB(255, 0, 0));

//            imshow("detect", frame);
//            waitKey(200);

        }

    }

}


void *read_video(void *arg) {


    VideoCapture video;

    if (false == video.open(-1)) {
        cout << "open error" << endl;
        return NULL;
    }
    cout << "open ok" << endl;


    while (1) {
        namedWindow("video");
        vector<unsigned char> buf;

        // double tstart1, tend1;
        // tstart1 = clock();

        //pthread_mutex_lock(&g_lock);
        if (false == video.read(frame)) {
            cout << "read error" << endl;
            continue;
        }
        //pthread_mutex_unlock(&g_lock);
        // cout << "read ok" << endl;
        imencode(".jpg", frame, buf);

        // pthread_mutex_lock(&g_lock);
        image = base64_encode((char *) buf.data(), buf.size());
        // pthread_mutex_unlock(&g_lock);

        imshow("video", frame);
        char c = waitKey(20);
        // if (c > 0)
        // {
        //         break;
        // }
        //sleep(1);
        //tend1 = clock();
        //cout<<(tend1-tstart1)/CLOCKS_PER_SEC<<endl;
    }
}


void* recevie(void* arg){
	int socket = *(int*)arg;
	while(1){
		char buf[1024];
		 size_t size = recv(socket, buf, sizeof(buf) - 1, 0);
		printf("client say : [%s]]\n", buf);
	}
}
int main() {



    //socket
    //创建的套接字是一个主动的套接字
    int servFd = socket(PF_INET, SOCK_STREAM, 0);
    if (servFd < 0) {
        perror("socket error!");
        return -1;
    }
    printf("socket ok!\n");
    //bind ip port
    struct sockaddr_in servAddr;
    memset(&servAddr, 0, sizeof(servAddr));
    servAddr.sin_family = PF_INET;
    servAddr.sin_port = htons(8888);
    servAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int ret = bind(servFd, (struct sockaddr *) &servAddr, sizeof(servAddr));
    if (ret < 0) {
        perror("bind error!");
        close(servFd);
        return -1;
    }
    printf("bind ok!\n");
    //listen
    //将主动的套接字变成被动的套接字
    ret = listen(servFd, 10);
    if (ret < 0) {
        perror("listen error!");
        close(servFd);
        return -1;
    }
    printf("listening....\n");
    //accept
    //客户端的地址信息
    struct sockaddr_in cliAddr = {0};
    socklen_t cliAddr_len = sizeof(cliAddr);
    int connFd = accept(servFd, (struct sockaddr *) &cliAddr, &cliAddr_len);
    if (connFd < 0) {
        perror("accept error!");
        close(servFd);
        return -1;
    }
    printf("accept ok!\n");
    printf("from IP = %s, port = %u\n", inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port));
    
    pthread_t tid1;
    int ret1 = pthread_create(&tid1, NULL, read_video, NULL);
    if (ret1 < 0) {
        perror("pthread_create");
        return 0;
    }


    pthread_t tid2;
    int ret2 = pthread_create(&tid2, NULL, search_face, NULL);
    if (ret2 < 0) {
        perror("pthread_create");
        return 0;
    }
    pthread_t tid3;
    int ret3 = pthread_create(&tid3, NULL, recevie, &connFd);
    if (ret3 < 0) {
        perror("pthread_create");
        return 0;
    }
    //recv
    while (1) {
//        char buf[1024] = {0};
//        ret = recv(connFd, buf, sizeof(buf), 0);
//        //ret = read(connFd, buf, sizeof(buf));
//        if (ret > 0) {
//            printf("recv from client:%s\n", buf);
//        }
//        memset(buf, 0, sizeof(buf));

        int n = sizeof(res) / sizeof(char);
       // if (n > 5 && flag == 1) {
            //发送数据 结果
	    while(res[0] != '\0'){
                 pthread_mutex_lock(&g_lock);

            	ret = send(connFd, res, sizeof(res), 0);
		memset(res, '\0', sizeof(res));
		pthread_mutex_unlock(&g_lock);
	    }
            if (ret < 0) {
                perror("send error!\n");
                close(servFd);
                close(connFd);
                return -1;
            }
           // printf("send ok!\n");
	    //sleep(2);
            //pthread_mutex_lock(&g_lock);
            //flag = 0;
            //pthread_mutex_unlock(&g_lock);
        //}


    }
    //close
    close(servFd);
    close(connFd);
    return 0;
}

